home *** CD-ROM | disk | FTP | other *** search
- ////////////////////////////////////////////////////
- // Huffman encoder implementation file huffenc.cpp
- // Copyright (c) 1991 Azarona Software
- // All rights reserved.
- ////////////////////////////////////////////////////
-
- #include "huffenc.h"
-
- huff_encoder::huff_encoder(int ns, int mcl)
- {
- int k;
- num_symbols = ns;
- max_code_len = mcl;
- codes = new unsigned[ns];
- code_lengths = new char[ns];
- for (k = 0; k<ns; k++) code_lengths[k] = 0;
- leaf_depths = new char[ns];
- counts = new long[ns];
- for (k = 0; k<ns; k++) counts[k] = 0;
- sorted_counts = new long[ns];
- smap = new unsigned char[ns];
- for (k = 0; k<ns; k++) smap[k] = k;
- reset_encoding();
- }
-
- huff_encoder::~huff_encoder(void)
- {
- delete[num_symbols] codes;
- delete[num_symbols] code_lengths;
- delete[num_symbols] leaf_depths;
- delete[num_symbols] counts;
- delete[num_symbols] smap;
- }
-
- int huff_encoder::generate_codes(void)
- // First sort weights in decreasing order, call package
- // merge to find the leaf depth (code length) of each
- // symbol, then, remap these depths so that they are
- // sorted in increasing order of depth, then,
- // generate the huffman codes from the sorted depth array.
- // Returns 1 if successful, 0 if not
- {
- int rv;
-
- for (rv = 0; rv<num_symbols; rv++) sorted_counts[rv] = counts[rv];
- qs(sorted_counts, smap, num_symbols);
- rv = package_merge(sorted_counts, smap, num_symbols,
- max_code_len, code_lengths);
- if (rv) {
- for (int k = 0; k<num_symbols; k++)
- leaf_depths[k] = code_lengths[smap[k]];
- make_codes(leaf_depths, codes, smap, num_symbols, max_code_len);
- }
- return rv;
- }
-
- void huff_encoder::reset_encoding(void)
- {
- currbyte = 0; currbit = 0;
- }
-
- void huff_encoder::flushbits(void)
- {
- if (currbit) {
- fputc(currbyte, fout);
- currbyte = 0; currbit = 0;
- }
- }
-
- union twobytes {
- unsigned code;
- struct {
- unsigned char ch1, ch2;
- } arr;
- };
-
- unsigned char mask[9] = {
- 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00
- };
-
- void huff_encoder::encode_symbol(int sym)
- {
- twobytes tb;
- tb.code = codes[sym];
- unsigned char nbits = code_lengths[sym];
-
- while(nbits) {
- unsigned char codebyte = (tb.arr.ch2 >> currbit);
- char blib = 8 - currbit;
- if (blib > nbits) { // Will have partial currbyte when through
- currbyte |= (codebyte & mask[blib-nbits]);
- currbit += nbits;
- return;
- }
- else { // Byte will be full, so transfer out
- currbyte |= codebyte;
- tb.code <<= blib;
- nbits -= blib;
- fputc(currbyte, fout);
- currbyte = 0; currbit = 0;
- }
- }
- }
-
-
- void huff_encoder::encode(FILE *fo, FILE *fi)
- {
- fout = fo; fin = fi;
-
- reset_encoding();
-
- while(!feof(fin)) {
- int c = fgetc(fin);
- if (c != -1) encode_symbol(c);
- }
-
- flushbits();
- }
-
- void huff_encoder::dump_codes(FILE *f, long locn)
- {
- fseek(f, locn, SEEK_SET);
- fwrite(&num_symbols, sizeof(int), 1, f);
- fwrite(codes, sizeof(unsigned), num_symbols, f);
- fwrite(code_lengths, sizeof(char), num_symbols, f);
- }
-
-
- void huff_encoder::print_bits(char nbits, unsigned code)
- {
- printf("%2d - ", nbits);
- for (int i = 0; i<nbits; i++) {
- if (code & 0x8000) putchar('1'); else putchar('0');
- code <<= 1;
- }
- }
-
-
- void huff_encoder::print_data(int show_sorted)
- {
- int j;
-
- printf("\n\nsym: count lv code\n\n");
-
- if (show_sorted) {
- for (j = 0; j<num_symbols; j++) {
- printf("%3d: %5lu ", smap[j], sorted_counts[j]);
- print_bits(leaf_depths[j], codes[smap[j]]);
- printf("\n");
- }
- }
- else {
- for (j = 0; j<num_symbols; j++) {
- printf("%3d: %5lu ", j, counts[j]);
- print_bits(code_lengths[j], codes[j]);
- printf("\n");
- }
- }
- }
-